#include "kernel/types.h"
#include "kernel/net.h"
#include "kernel/stat.h"
#include "user/user.h"

uint16 checksumcompute(uint32 dip, uint32 sip , uint16 proto, uint16 plen, uint16 *buffer,int size)
{
  uint32 cksum=0;/*32位长整数，检验和被置为0*/

  cksum += (dip>>16) + (dip&0xffff) + (sip>>16) + (sip&0xffff) + proto + plen;

  while (size>1){
    cksum +=*buffer++;
    size -=sizeof(uint16);
  }

  if (size) {
    /*处理剩余下来的字段，这些字段皆小于16位*/
    cksum +=*(uint8 *) buffer;
  }

  /*将32位转换为16位,高16位与低16位相加*/
  while (cksum>>16)
        cksum = (cksum>>16) + (cksum & 0xffff);
  return (uint16) (~cksum);
}

static void
checksumtest01()
{
  uint32 dst = (10 << 24) | (0 << 16) | (2 << 8) | (2 << 0);
  uint32 src = (10 << 24) | (0 << 16) | (2 << 8) | (3 << 0);  

  struct tcp *tcphdr=malloc(20);


  uint16 checksum = checksumcompute(dst, src, 0x0006, 20, (uint16 *)tcphdr, 20);
  if(checksum!=0xE7E0) {
    printf("test01 wrong implement!\n");
  } else {
    printf("test01 correct implement!\n");
  }
}

static void
checksumtest02()
{
  uint32 dst = (192 << 24) | (168 << 16) | (1 << 8) | (2 << 0);
  uint32 src = (192 << 24) | (168 << 16) | (1 << 8) | (103 << 0);  

  struct tcp *tcphdr=malloc(20);
  *((uint16*)tcphdr+1) = 1;
  *((uint16*)tcphdr+3) = 2;
  *((uint16*)tcphdr+5) = 3;
  *((uint16*)tcphdr+7) = 4;
  *((uint16*)tcphdr+9) = 5;
  *((uint16*)tcphdr+11) = 6;
  *((uint16*)tcphdr+13) = 7;

  uint16 checksum = checksumcompute(dst, src, 0x0006, 20, (uint16 *)tcphdr, 20);
  if(checksum!=0x7C1C) {
    printf("test02 wrong implement!\n");
  } else {
    printf("test02 correct implement!\n");
  }
}

static void
checksumtest03()
{
  uint32 dst = (176 << 24) | (168 << 16) | (1 << 8) | (2 << 0);
  uint32 src = (10 << 24) | (2 << 16) | (1 << 8) | (103 << 0);  

  struct tcp *tcphdr=malloc(20);
  *((uint16*)tcphdr+1) = 123;
  *((uint16*)tcphdr+3) = 77;
  *((uint16*)tcphdr+5) = 63;
  *((uint16*)tcphdr+7) = 14;
  *((uint16*)tcphdr+9) = 52;
  *((uint16*)tcphdr+11) = 36;
  *((uint16*)tcphdr+13) = 17;

  uint16 checksum = checksumcompute(dst, src, 0x0006, 20, (uint16 *)tcphdr, 20);
  if(checksum!=0x4189) {
    printf("test03 wrong implement!\n");
  } else {
    printf("test03 correct implement!\n");
  }
}


int
main(int argc, char *argv[])
{
  checksumtest01();
  checksumtest02();
  checksumtest03();
  exit(0);
}
